//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package user_resume_api_serv

import (
	"context"

	"atomgit.com/openlinksaas/api-server/api_common"
	"atomgit.com/openlinksaas/api-server/dao"
	"atomgit.com/openlinksaas/api-server/dao/org_dao"
	"atomgit.com/openlinksaas/api-server/dao/project_dao"
	"atomgit.com/openlinksaas/api-server/dao/user_dao"
	"atomgit.com/openlinksaas/api-server/utils"
	"atomgit.com/openlinksaas/proto-gen-go.git/notices/notices_org"
	"atomgit.com/openlinksaas/proto-gen-go.git/notices/notices_project"
	"atomgit.com/openlinksaas/proto-gen-go.git/user_resume_api"
	"go.mongodb.org/mongo-driver/mongo"
)

type UserResumeApiImpl struct {
	user_resume_api.UnimplementedUserResumeApiServer
}

func (apiImpl *UserResumeApiImpl) Set(ctx context.Context, req *user_resume_api.SetRequest) (*user_resume_api.SetResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &user_resume_api.SetResponse{
			Code:   user_resume_api.SetResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		basicInfo := user_dao.BasicInfoDbItem{
			TrueName:    req.ResumeInfo.BasicInfo.TrueName,
			Gender:      int32(req.ResumeInfo.BasicInfo.Gender),
			Birthday:    req.ResumeInfo.BasicInfo.Birthday,
			HasBirthDay: req.ResumeInfo.BasicInfo.HasBirthDay,
			MobilePhone: req.ResumeInfo.BasicInfo.MobilePhone,
			Email:       req.ResumeInfo.BasicInfo.Email,
			SelfIntro:   req.ResumeInfo.BasicInfo.SelfIntro,
		}
		workExpList := []user_dao.WorkExpDbItem{}
		for _, workExpItem := range req.ResumeInfo.WorkExpItemList {
			workExpList = append(workExpList, user_dao.WorkExpDbItem{
				FromTime:    workExpItem.FromTime,
				HasFromTime: workExpItem.HasFromTime,
				ToTime:      workExpItem.ToTime,
				HasToTime:   workExpItem.HasToTime,
				Company:     workExpItem.Company,
				Positon:     workExpItem.Positon,
				WorkDesc:    workExpItem.WorkDesc,
			})
		}
		eduExpList := []user_dao.EduExpDbItem{}
		for _, eduExpItem := range req.ResumeInfo.EduExpItemList {
			eduExpList = append(eduExpList, user_dao.EduExpDbItem{
				FromTime:    eduExpItem.FromTime,
				HasFromTime: eduExpItem.HasFromTime,
				ToTime:      eduExpItem.ToTime,
				HasToTime:   eduExpItem.HasToTime,
				SchoolName:  eduExpItem.SchoolName,
				MajorName:   eduExpItem.MajorName,
			})
		}
		err = user_dao.UserResumeDao.Set(sessCtx, &user_dao.UserResumeInfoDbItem{
			UserId:          sessionItem.UserId,
			BasicInfo:       basicInfo,
			WorkExpItemList: workExpList,
			EduExpItemList:  eduExpList,
		})
		if err != nil {
			return nil, err
		}
		err = user_dao.ResumeAccessDao.Set(sessCtx, &user_dao.ResumeAccessDbItem{
			UserId:             sessionItem.UserId,
			AllowProjectAccess: req.ResumeInfo.AllowProjectAccess,
			AllowOrgAccess:     req.ResumeInfo.AllowOrgAccess,
		})
		if err != nil {
			return nil, err
		}
		return &user_resume_api.SetResponse{
			Code: user_resume_api.SetResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送更新信息通知
	projectIdList, err := project_dao.MemberInfoDao.ListProjectByMember(ctx, sessionItem.UserId)
	if err == nil {
		for _, projectId := range projectIdList {
			go api_common.SendNoticeToProjectScope(context.Background(), projectId, &notices_project.UpdateMemberNotice{
				ProjectId:    projectId,
				MemberUserId: sessionItem.UserId,
			})
		}
	}
	orgIdList, err := org_dao.MemberDao.DistinctByUser(ctx, sessionItem.UserId)
	if err == nil {
		for _, orgId := range orgIdList {
			go api_common.SendNoticeToOrgScope(context.Background(), orgId, &notices_org.UpdateMemberNotice{
				OrgId:        orgId,
				MemberUserId: sessionItem.UserId,
			})
		}
	}
	return ret.(*user_resume_api.SetResponse), nil
}

func (apiImpl *UserResumeApiImpl) Get(ctx context.Context, req *user_resume_api.GetRequest) (*user_resume_api.GetResponse, error) {
	emptyInfo := &user_resume_api.UserResumeInfo{
		BasicInfo:       &user_resume_api.BasicInfo{},
		WorkExpItemList: []*user_resume_api.WorkExpItem{},
		EduExpItemList:  []*user_resume_api.EduExpItem{},
	}
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &user_resume_api.GetResponse{
			Code:       user_resume_api.GetResponse_CODE_WRONG_SESSION,
			ErrMsg:     "会话不存在",
			ResumeInfo: emptyInfo,
		}, nil
	}
	resumeItem, err := user_dao.UserResumeDao.Get(ctx, sessionItem.UserId)
	if err != nil {
		return &user_resume_api.GetResponse{
			Code:       user_resume_api.GetResponse_CODE_OK,
			ResumeInfo: emptyInfo,
		}, nil
	}
	accessItem, err := user_dao.ResumeAccessDao.Get(ctx, sessionItem.UserId)
	if err != nil {
		return &user_resume_api.GetResponse{
			Code:       user_resume_api.GetResponse_CODE_OK,
			ResumeInfo: emptyInfo,
		}, nil
	}

	return &user_resume_api.GetResponse{
		Code:       user_resume_api.GetResponse_CODE_OK,
		ResumeInfo: resumeItem.ToUserResumeInfo(accessItem),
	}, nil
}

func (apiImpl *UserResumeApiImpl) GetFromProject(ctx context.Context, req *user_resume_api.GetFromProjectRequest) (*user_resume_api.GetFromProjectResponse, error) {
	emptyInfo := &user_resume_api.UserResumeInfo{
		BasicInfo:       &user_resume_api.BasicInfo{},
		WorkExpItemList: []*user_resume_api.WorkExpItem{},
		EduExpItemList:  []*user_resume_api.EduExpItem{},
	}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &user_resume_api.GetFromProjectResponse{
			Code:       user_resume_api.GetFromProjectResponse_CODE_WRONG_SESSION,
			ErrMsg:     "会话不存在",
			ResumeInfo: emptyInfo,
		}, nil
	}

	exist, err := project_dao.ProjectInfoDao.Exist(ctx, req.ProjectId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &user_resume_api.GetFromProjectResponse{
			Code:       user_resume_api.GetFromProjectResponse_CODE_NO_PROJECT,
			ErrMsg:     "项目不存在",
			ResumeInfo: emptyInfo,
		}, nil
	}
	exist, err = project_dao.MemberInfoDao.Exist(ctx, req.ProjectId, sessionItem.UserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &user_resume_api.GetFromProjectResponse{
			Code:       user_resume_api.GetFromProjectResponse_CODE_NO_PERMISSION,
			ErrMsg:     "没有权限",
			ResumeInfo: emptyInfo,
		}, nil
	}
	if sessionItem.UserId != req.MemberUserId {
		exist, err = project_dao.MemberInfoDao.Exist(ctx, req.ProjectId, req.MemberUserId)
		if err != nil {
			return nil, err
		}
		if !exist {
			return &user_resume_api.GetFromProjectResponse{
				Code:       user_resume_api.GetFromProjectResponse_CODE_NO_MEMBER,
				ErrMsg:     "项目成员不存在",
				ResumeInfo: emptyInfo,
			}, nil
		}
	}
	accessItem, err := user_dao.ResumeAccessDao.Get(ctx, req.MemberUserId)
	if err != nil {
		return &user_resume_api.GetFromProjectResponse{
			Code:       user_resume_api.GetFromProjectResponse_CODE_OK,
			ResumeInfo: emptyInfo,
		}, nil
	}
	if !accessItem.AllowProjectAccess {
		return &user_resume_api.GetFromProjectResponse{
			Code:       user_resume_api.GetFromProjectResponse_CODE_OK,
			ResumeInfo: emptyInfo,
		}, nil
	}
	resumeItem, err := user_dao.UserResumeDao.Get(ctx, req.MemberUserId)
	if err != nil {
		return &user_resume_api.GetFromProjectResponse{
			Code:       user_resume_api.GetFromProjectResponse_CODE_OK,
			ResumeInfo: emptyInfo,
		}, nil
	}

	return &user_resume_api.GetFromProjectResponse{
		Code:       user_resume_api.GetFromProjectResponse_CODE_OK,
		ResumeInfo: resumeItem.ToUserResumeInfo(accessItem),
	}, nil
}

func (apiImpl *UserResumeApiImpl) GetFromOrg(ctx context.Context, req *user_resume_api.GetFromOrgRequest) (*user_resume_api.GetFromOrgResponse, error) {
	emptyInfo := &user_resume_api.UserResumeInfo{
		BasicInfo:       &user_resume_api.BasicInfo{},
		WorkExpItemList: []*user_resume_api.WorkExpItem{},
		EduExpItemList:  []*user_resume_api.EduExpItem{},
	}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &user_resume_api.GetFromOrgResponse{
			Code:       user_resume_api.GetFromOrgResponse_CODE_WRONG_SESSION,
			ErrMsg:     "会话不存在",
			ResumeInfo: emptyInfo,
		}, nil
	}
	orgItem, err := org_dao.OrgInfoDao.Get(ctx, req.OrgId)
	if err != nil {
		return &user_resume_api.GetFromOrgResponse{
			Code:       user_resume_api.GetFromOrgResponse_CODE_NO_ORG,
			ErrMsg:     "组织不存在",
			ResumeInfo: emptyInfo,
		}, nil
	}
	targetMemberItem, err := org_dao.MemberDao.Get(ctx, req.OrgId, req.MemberUserId)
	if err != nil {
		return &user_resume_api.GetFromOrgResponse{
			Code:       user_resume_api.GetFromOrgResponse_CODE_NO_MEMBER,
			ErrMsg:     "团队成员不存在",
			ResumeInfo: emptyInfo,
		}, nil
	}
	if orgItem.OwnerUserId != sessionItem.UserId {
		curMemberItem, err := org_dao.MemberDao.Get(ctx, req.OrgId, sessionItem.UserId)
		if err != nil {
			return &user_resume_api.GetFromOrgResponse{
				Code:       user_resume_api.GetFromOrgResponse_CODE_NO_PERMISSION,
				ErrMsg:     "没有权限",
				ResumeInfo: emptyInfo,
			}, nil
		}

		ok, err := utils.CheckIncludeDepartMent(ctx, req.OrgId, targetMemberItem.ParentDepartMentId, curMemberItem.ParentDepartMentId)
		if err != nil {
			return nil, err
		}
		if !ok {
			return &user_resume_api.GetFromOrgResponse{
				Code:       user_resume_api.GetFromOrgResponse_CODE_NO_PERMISSION,
				ErrMsg:     "没有权限",
				ResumeInfo: emptyInfo,
			}, nil
		}
	}
	accessItem, err := user_dao.ResumeAccessDao.Get(ctx, req.MemberUserId)
	if err != nil {
		return &user_resume_api.GetFromOrgResponse{
			Code:       user_resume_api.GetFromOrgResponse_CODE_OK,
			ResumeInfo: emptyInfo,
		}, nil
	}
	if !accessItem.AllowOrgAccess {
		return &user_resume_api.GetFromOrgResponse{
			Code:       user_resume_api.GetFromOrgResponse_CODE_OK,
			ResumeInfo: emptyInfo,
		}, nil
	}
	resumeItem, err := user_dao.UserResumeDao.Get(ctx, req.MemberUserId)
	if err != nil {
		return &user_resume_api.GetFromOrgResponse{
			Code:       user_resume_api.GetFromOrgResponse_CODE_OK,
			ResumeInfo: emptyInfo,
		}, nil
	}

	return &user_resume_api.GetFromOrgResponse{
		Code:       user_resume_api.GetFromOrgResponse_CODE_OK,
		ResumeInfo: resumeItem.ToUserResumeInfo(accessItem),
	}, nil
}
